package com.wolfheader.wolfgame;

import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

import com.wolfheader.wolfgame.shiro.AdminShiroFilterFactoryBean;
import com.wolfheader.wolfgame.shiro.AdminShiroRealm;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;

/**
 * Shiro 配置
 */
@Configuration
public class ShiroConfiguration {
	private static final Logger logger = LoggerFactory.getLogger(ShiroConfiguration.class);

	@Bean
	public EhCacheManager getEhCacheManager() {
		EhCacheManager em = new EhCacheManager();
		em.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
		return em;
	}

	@Bean(name = "adminShiroRealm")
	@DependsOn("lifecycleBeanPostProcessor")  
	public AdminShiroRealm adminShiroRealm(EhCacheManager cacheManager) {
		AdminShiroRealm realm = new AdminShiroRealm();
		realm.setAuthenticationCacheName("authorization");
		realm.setCacheManager(cacheManager);
		return realm;
	}

	/**
	 * 注册DelegatingFilterProxy（Shiro） 集成Shiro有2种方法： 1.
	 * 按这个方法自己组装一个FilterRegistrationBean（这种方法更为灵活，可以自己定义UrlPattern，
	 * 在项目使用中你可能会因为一些很但疼的问题最后采用它， 想使用它你可能需要看官网或者已经很了解Shiro的处理原理了） 2.
	 * 直接使用ShiroFilterFactoryBean（这种方法比较简单，其内部对ShiroFilter做了组装工作，
	 * 无法自己定义UrlPattern， 默认拦截 /*）
	 *
	 * @param dispatcherServlet
	 * @return
	 * @author SHANHY
	 * @create 2016年1月13日
	 */
	// @Bean
	// public FilterRegistrationBean filterRegistrationBean() {
	// FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
	// filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));
	// //
	// 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理
	// filterRegistration.addInitParameter("targetFilterLifecycle", "true");
	// filterRegistration.setEnabled(true);
	// filterRegistration.addUrlPatterns("/*");//
	// 可以自己灵活的定义很多，避免一些根本不需要被Shiro处理的请求被包含进来
	// return filterRegistration;
	// }

	@Bean(name = "validator")
	public LocalValidatorFactoryBean getLocalValidatorFactoryBean() {
		LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
		// MessageSource
		// bean.setValidationMessageSource();
		//// bean.setProviderClass(Hibernat);
		return bean;
	}

	@Bean(name = "lifecycleBeanPostProcessor")
	public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
		return new LifecycleBeanPostProcessor();
	}

	@Bean(name = "shiroDialect")  
	public ShiroDialect shiroDialect() {
		return new ShiroDialect();
	}

	@Bean
	public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
		DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
		daap.setProxyTargetClass(true);
		return daap;
	}

	@Bean(name = "securityManager")
	public DefaultWebSecurityManager getDefaultWebSecurityManager(AdminShiroRealm adminShiroRealm) {
		DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
		dwsm.setRealm(adminShiroRealm);
		dwsm.setCacheManager(getEhCacheManager());
		return dwsm;
	}

	@Bean
	public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(
			DefaultWebSecurityManager securityManager) {
		AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
		aasa.setSecurityManager(securityManager);
		return aasa;
	}

	/**
	 * 加载shiroFilter权限控制规则（从数据库读取然后配置）
	 *
	 * @author SHANHY
	 * @create 2016年1月14日
	 */
	private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean) {
		/////////////////////// 下面这些规则配置最好配置到配置文件中 ///////////////////////
		Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
		// authc：该过滤器下的页面必须验证后才能访问，它是Shiro内置的一个拦截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter
		// anon：它对应的过滤器里面是空的,什么都没做
		logger.info("##################从数据库读取权限规则，加载到shiroFilter中##################");
		/*filterChainDefinitionMap.put("/admin/**","authc,roles[admin]");  
		filterChainDefinitionMap.put("/admin/product/**", "perms[product:all]");
		filterChainDefinitionMap.put("/admin/person/**", "perms[person:all]");
		filterChainDefinitionMap.put("/admin/role/**", "perms[role:all]");
		filterChainDefinitionMap.put("/admin/admin/**", "perms[admin:all]");
		filterChainDefinitionMap.put("/admin/permission/**", "perms[permission:all]");
		filterChainDefinitionMap.put("/admin/modif/**", "perms[admin:modif]");
		filterChainDefinitionMap.put("/admin/delete/**", "perms[admin:delete]");
		filterChainDefinitionMap.put("/admin/game/**", "perms[game:all]");  
		filterChainDefinitionMap.put("/admin/login", "authc");*/
		filterChainDefinitionMap.put("/admin/**", "authc");
		// filterChainDefinitionMap.put("/**", "anon");// anon 可以理解为不拦截
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
	}

	/**
	 * ShiroFilter<br/>
	 * 注意这里参数中的 StudentService 和 IScoreDao 只是一个例子，因为我们在这里可以用这样的方式获取到相关访问数据库的对象，
	 * 然后读取数据库相关配置，配置到 shiroFilterFactoryBean 的访问规则中。实际项目中，请使用自己的Service来处理业务逻辑。
	 *
	 * @param myShiroRealm
	 * @param stuService
	 * @param scoreDao
	 * @return
	 * @author SHANHY
	 * @create 2016年1月14日
	 */
	@Bean(name = "shiroFilter")
	public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
		ShiroFilterFactoryBean shiroFilterFactoryBean = new AdminShiroFilterFactoryBean();
		// 必须设置 SecurityManager
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
		shiroFilterFactoryBean.setLoginUrl("/admin/login");
		// 登录成功后要跳转的连接
		shiroFilterFactoryBean.setSuccessUrl("/admin/index");
		shiroFilterFactoryBean.setUnauthorizedUrl("/admin/403");
		loadShiroFilterChain(shiroFilterFactoryBean);
		return shiroFilterFactoryBean;
	}

}
